﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using Windows8Accelerator.Core.Xaml.Converters;
using Windows8Accelerator.Core.Xaml.Helpers;

namespace Windows8Accelerator.Core.Xaml.Controls
{
    public enum SuperFlyoutCloseReason
    {
        BackButton,
        LightDismissal,
        Other
    }

    public enum SuperFlyoutPosition
    {
        Right,
        Center
    }

    public static class SuperFlyoutHelper
    {
        public static SuperFlyout ShowSuperFlyout(this Panel hostPanel, string headerText, double width, Brush background, UIElement content, Brush headerBackground = null, SuperFlyoutPosition position = SuperFlyoutPosition.Right, double height = double.NaN, Brush headerForeground = null, Brush foreground = null)
        {
            var superFlyout = new SuperFlyout(true, position)
            {
                HeaderText = headerText,
                Width = width,
                Height = height,
                Background = background ?? new SolidColorBrush(Colors.White),
                HeaderBackground = headerBackground ?? new SolidColorBrush(Colors.White),
                Content = content,
                HeaderForeground = headerForeground ?? new SolidColorBrush(Colors.Black),
                Foreground = foreground ?? new SolidColorBrush(Colors.Black),
            };
            superFlyout.Loaded += (s, e) => ((SuperFlyout)s).Show();
            hostPanel.Children.Add(superFlyout);
            return superFlyout;
        }

        public static SuperFlyout ShowSuperImageFlyout(Panel panel, string imageSrc, SolidColorBrush background, Thickness imageMargin, SolidColorBrush borderBrush, Thickness borderThickness)
        {
            var image = new Image();
            image.Margin = imageMargin;
            image.MaxHeight = Window.Current.Bounds.Height * 0.9;
            image.MaxWidth = Window.Current.Bounds.Width * 0.9;
            image.Stretch = Stretch.Uniform;
            var stringToImageConverter = new StringToImageConverter();
            image.Source = stringToImageConverter.Convert(imageSrc, typeof(ImageSource), null, null) as ImageSource;
        
            var superFlyout = new SuperFlyout(true, SuperFlyoutPosition.Center)
            {
                HeaderText = "",
                Background = background,
                Content = image,
                BorderThickness = borderThickness,
                BorderBrush = borderBrush,
                Width = double.NaN,
                Height = double.NaN,
            };
            superFlyout.Loaded += (s, e) => ((SuperFlyout)s).Show();
            panel.Children.Add(superFlyout);
            return superFlyout;
        }

        public static SuperFlyout ShowSuperWebViewFlyout(Panel panel, string url, SolidColorBrush background, Thickness webViewMargin, Thickness screenMargin, SolidColorBrush borderBrush, Thickness borderThickness, Action<WebView, SuperFlyout> initializeWebView = null)
        {
            var webView = new WebView();
            webView.Margin = webViewMargin;
            var superFlyout = new SuperFlyout(true, SuperFlyoutPosition.Center)
            {
                HeaderText = "",
                Background = background,
                Content = webView,
                BorderThickness = borderThickness,
                BorderBrush = borderBrush,
                Width = Window.Current.Bounds.Width - screenMargin.Left - screenMargin.Right,
                Height = Window.Current.Bounds.Height - screenMargin.Top - screenMargin.Bottom,
            };
            if (initializeWebView != null)
                initializeWebView(webView, superFlyout);
            superFlyout.Loaded += (s, e) => 
            {
                ((SuperFlyout)s).Show();
                webView.Navigate(new Uri(url));
            };
            panel.Children.Add(superFlyout);
            return superFlyout;
        }

        public static SuperFlyout ShowControlOnSuperFlyout(Panel panel, FrameworkElement control, SolidColorBrush background, Thickness webViewMargin, Thickness screenMargin, SolidColorBrush borderBrush, Thickness borderThickness)
        {
            control.Margin = webViewMargin;
            var superFlyout = new SuperFlyout(true, SuperFlyoutPosition.Center)
            {
                HeaderText = "",
                Background = background,
                Content = control,
                BorderThickness = borderThickness,
                BorderBrush = borderBrush,
                Width = Window.Current.Bounds.Width - screenMargin.Left - screenMargin.Right,
                Height = Window.Current.Bounds.Height - screenMargin.Top - screenMargin.Bottom,
            };
            superFlyout.Loaded += (s, e) =>
            {
                ((SuperFlyout)s).Show();
            };
            panel.Children.Add(superFlyout);
            return superFlyout;
        }

        public static void CloseParentFlyout(FrameworkElement control)
        {
            var parentFlyout = control.Parent as SuperFlyout;
            if (parentFlyout != null)
                parentFlyout.Hide(SuperFlyoutCloseReason.Other);
        }
    }

    public class SuperFlyout : ContentControl
    {
        public SuperFlyout(bool removeFromParentOnHide, SuperFlyoutPosition position)
            :this()
        {
            RemoveFromParentOnHide = removeFromParentOnHide;
            Position = position;
            Style = GetStyle(position);
        }

        private static Style GetStyle(SuperFlyoutPosition position)
        {
            var resourceDictionary = new ResourceDictionary();
            resourceDictionary.Source = new Uri("ms-appx:///W8A.C.X/Themes/Generic.xaml");

            switch (position)
            {
                case SuperFlyoutPosition.Right:
                    return resourceDictionary["RightSuperFlyoutStyle"] as Style;
                case SuperFlyoutPosition.Center:
                    return resourceDictionary["CenteredSuperFlyoutStyle"] as Style;
            }

            return null;
        }

        public SuperFlyout() 
        {
            DefaultStyleKey = typeof(SuperFlyout);
            SetBinding(Control.BorderBrushProperty, new Binding() { 
                Source = this,
                Path = new PropertyPath("Background"),
                Converter = new BackgroundColorToBorderColorConverter()
            });
        }

        public new Brush Background
        {
            get { return (Brush)GetValue(BackgroundProperty); }
            set { SetValue(BackgroundProperty, value); }
        }
        public new static readonly DependencyProperty BackgroundProperty =
            DependencyProperty.Register("Background", typeof(Brush), typeof(SuperFlyout), new PropertyMetadata(null));

        public delegate void AddOnClosingDelegate(object sender, SuperFlyoutCloseReason reason);
        public event AddOnClosingDelegate OnClosing;
        private Popup Popup;
        public void OnClosingEvent(object sender, SuperFlyoutCloseReason reason)
        {
            if (OnClosing != null)
                OnClosing(sender, reason);
        }

        protected override void OnApplyTemplate()
        {
            TemplatePopup = GetTemplateChild("Popup") as ContentControl;
            var backButton = GetTemplateChild("BackButton") as Button;
            if (backButton != null)
            { 
                backButton.Click += (sender, e) =>  Hide(SuperFlyoutCloseReason.BackButton);
            }
            if (TemplatePopup != null)
            {
                if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
                {
                    TemplatePopup.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                }
            }
        }

        private bool ListeningToOnWindowActivated;
        private ContentControl TemplatePopup;

        public virtual void Show()
        {
            if (InternalContent == null && TemplatePopup != null)
            {
                InternalContent = TemplatePopup.Content as FrameworkElement;
                TemplatePopup.Content = null;
            }

            Popup = new Popup();
            Popup.IsLightDismissEnabled = true;
            Popup.Child = InternalContent;
            Popup.Closed += PopupClosed;

            InternalContent.SizeChanged += (s, e) => {
                if (VerticalContentAlignment != VerticalAlignment.Stretch)
                    Height = e.NewSize.Height;
                if (HorizontalContentAlignment != HorizontalAlignment.Stretch)
                    Width = e.NewSize.Width;
                UpdatePopupPosition();
            };

            UpdatePopupPosition();

            Popup.IsOpen = true;
            if (!ListeningToOnWindowActivated)
            {
                Window.Current.Activated += OnWindowActivated;
                ListeningToOnWindowActivated = true;
            }
        }

        private void UpdatePopupPosition()
        {
            switch (Position)
            {
                case SuperFlyoutPosition.Right:
                    Height = Window.Current.Bounds.Height;
                    if (!Width.Equals(double.NaN))
                        Canvas.SetLeft(Popup, Window.Current.Bounds.Width - Width);
                    break;
                case SuperFlyoutPosition.Center:
                    if (!Width.Equals(double.NaN))
                        Canvas.SetLeft(Popup, (Window.Current.Bounds.Width - Width) / 2);
                    if (!Height.Equals(double.NaN))
                        Canvas.SetTop(Popup, (Window.Current.Bounds.Height - Height) / 2);
                    break;
                default:
                    break;
            }
        }

        public void Hide(SuperFlyoutCloseReason reason)
        {
            OnClosingEvent(this, reason);
            if (ListeningToOnWindowActivated)
            {
                Window.Current.Activated -= OnWindowActivated;
                ListeningToOnWindowActivated = false;
            }
            Canvas.SetLeft(Popup, Window.Current.Bounds.Width);
            Popup.Child = null;
            if (RemoveFromParentOnHide)
            {
                var parent = this.GetParentOf<Panel>();
                if (parent != null)
                    parent.Children.Remove(this);
            }
        }

        private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
        {
            if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
            {
                Hide(SuperFlyoutCloseReason.Other);
            }
        }

        private void PopupClosed(object sender, object e)
        {
            Hide(SuperFlyoutCloseReason.LightDismissal);
        }



        public Style HeaderTextBlockStyle
        {
            get { return (Style)GetValue(HeaderTextBlockStyleProperty); }
            set { SetValue(HeaderTextBlockStyleProperty, value); }
        }
        public static readonly DependencyProperty HeaderTextBlockStyleProperty =
            DependencyProperty.Register("HeaderTextBlockStyle", typeof(Style), typeof(SuperFlyout), new PropertyMetadata(null));

        public string HeaderText
        {
            get { return (string)GetValue(HeaderTextProperty); }
            set { SetValue(HeaderTextProperty, value); }
        }
        public static readonly DependencyProperty HeaderTextProperty =
            DependencyProperty.Register("HeaderText", typeof(string), typeof(SuperFlyout), new PropertyMetadata(null));

        public Style BackButtonStyle
        {
            get { return (Style)GetValue(BackButtonStyleProperty); }
            set { SetValue(BackButtonStyleProperty, value); }
        }
        public static readonly DependencyProperty BackButtonStyleProperty =
            DependencyProperty.Register("BackButtonStyle", typeof(Style), typeof(SuperFlyout), new PropertyMetadata(null));



        public Brush HeaderForeground
        {
            get { return (Brush)GetValue(HeaderForegroundProperty); }
            set { SetValue(HeaderForegroundProperty, value); }
        }
        public static readonly DependencyProperty HeaderForegroundProperty =
            DependencyProperty.Register("HeaderForeground", typeof(Brush), typeof(SuperFlyout), new PropertyMetadata(null));
       
        public Brush HeaderBackground
        {
            get { return (Brush)GetValue(HeaderBackgroundProperty); }
            set { SetValue(HeaderBackgroundProperty, value); }
        }
        public static readonly DependencyProperty HeaderBackgroundProperty =
            DependencyProperty.Register("HeaderBackground", typeof(Brush), typeof(SuperFlyout), new PropertyMetadata(null));

        public FrameworkElement InternalContent;

        public SuperFlyoutPosition Position
        {
            get { return (SuperFlyoutPosition)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }
        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(SuperFlyoutPosition), typeof(SuperFlyout), new PropertyMetadata(SuperFlyoutPosition.Right));
       
        public bool RemoveFromParentOnHide { get; set; }
    }
}
